﻿#region COPYRIGHT
//--------------------------------------------------------------------------------
// <copyright file="SpriteBatchExtensions.cs" company="starLiGHT Entertainment Studios">
//    Copyright (c) 2007, 2008, 2009, 2010 
//       Roland Rosenkranz (Glatzemann@email.de)
// </copyright>
// <license>
//   This file is part of starLiGHT.Core.
//
//   starLiGHT.Core is free software: you can redistribute it and/or modify
//   it under the terms of the GNU Lesser General Public License as published by
//   the Free Software Foundation, either version 3 of the License, or
//   (at your option) any later version.
//
//   starLiGHT.Core is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU Lesser General Public License for more details.
//
//   You should have received a copy of the GNU Lesser General Public License
//   along with starLiGHT.Core. If not, see http://www.gnu.org/licenses/.
//    
//   ADDITIONAL (commercial) LICENSES for starLiGHT.Core are available on request.
// </license>
// <version>
// **************[ starLiGHT.Engine SVN ]**********************
// * $Rev:: 620                   $:  Revision of last commit *
// * $Author:: unknown            $:  Author of last commit   *
// * $Date:: 2010-12-07 15:23:58 #$:  Date of last commit     *
// ************************************************************
// </version>
//--------------------------------------------------------------------------------
#endregion

namespace starLiGHT
{
    #region Using Statements
    using System;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Graphics;

    #endregion

    /// <summary>
    /// Extension methods for XNA's SpriteBatch
    /// </summary>
    public static class SpriteBatchExtensions
    {
        private static Texture2D pixel;
        private static RectangleF tempRectF;
        private static Vector2[] tempVertices;

        public static void Draw(this SpriteBatch spriteBatch, Texture2D texture, RectangleF destinationRectangle, Color tint)
        {
            spriteBatch.Draw(texture, destinationRectangle.ToRectangle(), tint);
        }

        public static void DrawLine(this SpriteBatch spriteBatch, Vector2 start, Vector2 end, Color color)
        {
            DrawLine(spriteBatch, start, end, 1.0f, color);
        }

        public static void DrawLine(this SpriteBatch spriteBatch, Vector2 start, Vector2 end, float width, Color color)
        {
            CreatePixel(spriteBatch.GraphicsDevice);

            float length;
            Vector2.Distance(ref start, ref end, out length);

            float hw = width * 0.5f;
            float angle = (float)Math.Atan2(end.Y - start.Y, end.X - start.X);
            float cos = hw * (float)Math.Cos(angle);
            float sin = hw * (float)Math.Sin(angle);

            start.X -= cos - sin;
            start.Y -= cos + sin;

            end.X += cos - sin;
            end.Y += cos + cos;

            spriteBatch.Draw(pixel, start, null, color, angle, Vector2.Zero, new Vector2(length, width), SpriteEffects.None, 0);
        }

        public static void DrawCircle(this SpriteBatch spriteBatch, Vector2 center, float radius, int segments, Color color)
        {
            DrawCircle(spriteBatch, center, radius, segments, 1.0f, color);
        }

        public static void DrawCircle(this SpriteBatch spriteBatch, Vector2 center, float radius, int segments, float lineWidth, Color color)
        {
            if (tempVertices == null || tempVertices.Length != segments)
            {
                float increment = (float)MathHelper.TwoPi / segments;
                tempVertices = new Vector2[segments];

                for (int i = 0; i < segments; i++)
                {
                    tempVertices[i].X = (float)Math.Cos(increment * i);
                    tempVertices[i].Y = (float)Math.Sin(increment * i);
                }
            }

            for (int i = 0; i < segments - 1; i++)
            {
                DrawLine(
                         spriteBatch, 
                         center + (tempVertices[i] * radius), 
                         center + (tempVertices[i + 1] * radius), 
                         lineWidth, 
                         color);
            }

            DrawLine(
                spriteBatch, 
                center + (tempVertices[segments - 1] * radius), 
                center + (tempVertices[0] * radius), 
                lineWidth, 
                color);
        }

        public static void DrawBox(this SpriteBatch spriteBatch, Rectangle rectangle, Color color)
        {
            spriteBatch.DrawBox(rectangle.ToRectangleF(), color);
        }

        public static void DrawBox(this SpriteBatch spriteBatch, RectangleF rectangle, Color color)
        {
            spriteBatch.DrawLine(rectangle.TopLeft, rectangle.TopRight, color);
            spriteBatch.DrawLine(rectangle.TopRight, rectangle.BottomRight, color);
            spriteBatch.DrawLine(rectangle.BottomRight, rectangle.BottomLeft, color);
            spriteBatch.DrawLine(rectangle.BottomLeft, rectangle.TopLeft, color);
        }

        public static void DrawRectangle(this SpriteBatch spriteBatch, Rectangle rectangle, Color color)
        {
            CreatePixel(spriteBatch.GraphicsDevice);
            spriteBatch.Draw(pixel, rectangle, color);
        }

        public static void DrawRectangle(this SpriteBatch spriteBatch, RectangleF rectangle, Color color)
        {
            CreatePixel(spriteBatch.GraphicsDevice);
            spriteBatch.Draw(pixel, rectangle.ToRectangle(), color);
        }

        public static void DrawRectangle(this SpriteBatch spriteBtach, float x, float y, float width, float height, Color color)
        {
            if (tempRectF == null)
            {
                tempRectF = new RectangleF();
            }

            tempRectF.X = x;
            tempRectF.Y = y;
            tempRectF.Width = width;
            tempRectF.Height = height;
            CreatePixel(spriteBtach.GraphicsDevice);
            spriteBtach.Draw(pixel, tempRectF.ToRectangle(), color);
        }

        private static void CreatePixel(GraphicsDevice graphics)
        {
            if (pixel == null)
            {
                pixel = new Texture2D(graphics, 1, 1);
                pixel.SetData<Color>(new Color[] { Color.White });
            }
        }
    }
}
